/*******************************************************************************
 * Copyright (c) 2007 CEA LIST.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     OBEO (www.obeo.fr) - initial API and implementation
 *     CEA LIST
 *******************************************************************************/
package com.cea.papyrus.core.editor;

import java.io.FileNotFoundException;

import org.eclipse.core.resources.IFile;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.ResourceUtil;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.uml2.uml.Model;
import org.eclipse.uml2.uml.Package;

import com.cea.papyrus.core.IPapyrusUIConstants;
import com.cea.papyrus.core.utils.Debug;

/**
 * This class is used to open a model file in Papyrus from external tools.
 * Very important : these method will usually require to be started in
 *  the UI thread.
 *  
 *  		PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
 *			public void run() {
 *				try {
 *					called_method;
 *				}
 *			});
 */
public class EditorUtils {

	/**
	 * Gets the UML model opened by Papyrus editor
	 * 
	 * @param papyrusInstance
	 *            the papyrus editor instance
	 * 
	 * @return the model
	 */
	public static Model getModel(MultiDiagramEditor papyrusInstance) {
		// Retrieve model managed by Papyrus
		ModelManager modelManager = papyrusInstance.getModelManager();

		Package topPackage = modelManager.getTopPackageFromUMLResource();
		if (!(topPackage instanceof Model)) {
			Debug.log(new Exception(
					"File opened in Papyrus doesn't seem to be a model."));
			return null;
		}

		return (Model) topPackage;
	}

	/**
	 * Static method that tries to retrieve existing instance of Papyrus which
	 * edit the model (or the model in Papyrus if it does not exist).
	 * 
	 * @param activePage
	 *            the active page
	 * @param modelIFile
	 *            the model file
	 * 
	 * @return the Papyrus MultiDiagramEditor
	 */
	public static MultiDiagramEditor getPapyrusEditor(
			final IWorkbenchPage activePage, final IFile modelIFile) {

		// Get the Papyrus editor that opens the file
		// Problem may occur if multiple editors are opening the di2 file
		// at the same time.
		if (ResourceUtil.findEditor(activePage, modelIFile) == null) {
			EditorUtils.openFileWithPapyrus(activePage, modelIFile);
		}

		IEditorPart editorPart = ResourceUtil
				.findEditor(activePage, modelIFile);
		if (editorPart instanceof MultiDiagramEditor) {
			return (MultiDiagramEditor) editorPart;
		}

		// Papyrus editor was not retrieved (or opened).
		String errMsg = "Unable to find the papyrus instance that opens the file "
				+ modelIFile.getName() + " with Papyrus.";
		Debug.log(new FileNotFoundException(errMsg));
		return null;
	}

	/**
	 * Gets (or create) the papyrus instance with modelFile opened.
	 * 
	 * @param modelFile
	 *            the model file
	 * 
	 * @return the papyrus editor instance
	 */
	public static MultiDiagramEditor getPapyrusInstance(IFile modelFile) {
		// Retrieve WorkbenchWindow
		IWorkbenchWindow workbenchWindow = EditorUtils.getWorkbenchWindow();
		if (workbenchWindow == null) {
			Debug.log(new Exception("Unable to retriev WorkbenchWindow"));
			return null;
		}
		// Retrieve WorkbenchPage
		IWorkbenchPage activePage = workbenchWindow.getActivePage();
		if (activePage == null) {
			Debug.log(new Exception("Unable to find ActivePage"));
			return null;
		}

		return EditorUtils.getPapyrusEditor(activePage, modelFile);
	}

	/**
	 * Static method to retrieve the workbench window, testing result of
	 * getActiveWorkbenchWindow first.
	 * 
	 * @return the IWorkbenchWindow
	 */
	public static IWorkbenchWindow getWorkbenchWindow() {

		IWorkbench workbench = PlatformUI.getWorkbench();
		if (workbench == null) {
			Debug.log(new Exception("Workbench not found."));
		}

		if (workbench.getActiveWorkbenchWindow() != null) {
			return workbench.getActiveWorkbenchWindow();
		} else {
			IWorkbenchWindow[] workbenchWindows = PlatformUI.getWorkbench()
					.getWorkbenchWindows();

			if ((workbenchWindows != null) || (workbenchWindows.length > 0)) {
				return workbenchWindows[0];
			}
		}

		Debug.log(new Exception("Workbench window not found."));
		return null;
	}

	/**
	 * Static method that tries to open the model (modelIFile) with Papyrus.
	 * 
	 * @param activePage
	 *            the active page
	 * @param modelIFile
	 *            the model file
	 */
	public static void openFileWithPapyrus(final IWorkbenchPage activePage,
			final IFile modelIFile) {

		IEditorInput input = new FileEditorInput(modelIFile);
		try {
			// Try to open file with Papyrus
			activePage.openEditor(input, IPapyrusUIConstants.EDITOR_ID);
		} catch (PartInitException e) {
			Debug.log(e);
		}
	}
}
